<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
 <head>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <title>子组(子模式)</title>

 </head>
 <body><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="regexp.reference.internal-options.html">内部选项设置</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="regexp.reference.repetition.html">重复/量词</a></div>
 <div class="up"><a href="reference.pcre.pattern.syntax.html">PCRE 正则语法</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div><hr /><div id="regexp.reference.subpatterns" class="section">
  <h2 class="title">子组(子模式)</h2>
  <p class="para">
  子组通过圆括号分隔界定，并且它们可以嵌套。
  将一个模式中的一部分标记为子组(子模式)主要是来做两件事情：
  </p>
  <ol type="1">
   <li class="listitem">
    <p class="para">
    将可选分支局部化。比如，模式<em>cat(arcat|erpillar|)</em>匹配 ”cat”， “cataract”，
    “caterpillar” 中的一个，如果没有圆括号的话，它匹配的则是 ”cataract”，
    “erpillar” 以及空字符串。
    </p>
   </li>
   <li class="listitem">
    <p class="para">
    将子组设定为捕获子组(向上面定义的). 当整个模式匹配后，
    目标字符串中匹配子组的部分将会通过 <span class="function"><strong>pcre_exec()()</strong></span> 的 <em class="emphasis">ovector</em> 参数回传给调用者。
    左括号从左至右出现的次序就是对应子组的下标(从 1 开始)，
    可以通过这些下标数字来获取捕获子模式匹配结果。
    </p>
   </li>
  </ol>
  <p class="para">
  比如，如果字符串 ”the red king” 使用模式<em>((red|white)
  (king|queen))</em> 进行匹配，
  模式匹配到的结果是 array(“red king”， ”red king”, “red”, “king”) 的形式，
  其中第 0 个元素是整个模式匹配的结果，后面的三个元素依次为三个子组匹配的结果。
  它们的下表分别为 1， 2， 3。
  </p>
  <p class="para">
  事实上，圆括号履行的两种功能并不总是有用的。
  经常我们会有一种需求需要使用子组进行分组， 但又不需要(单独的)捕获它们。
  在子组定义的左括号后面紧跟字符串 ”?:” 会使得该子组不被单独捕获，
  并且不会对其后子组序号的计算产生影响。比如, 如果字符串 ”the white
  queen” 匹配模式 <em>((?:red|white) (king|queen))</em>，匹配到的结果会是 array(“white
  queen”、“white queen”、“white queen”)，的和 king|queen 这两个子组。 捕获子组序号的最大值是 99，
  最大允许拥有的所有子组(包括捕获的和非捕获的)的最大数量为 200。
  </p>
  <p class="para">
  为了方便简写，如果需要在非捕获子组开始位置设置选项，
  选项字母可以位于 ? 和 : 之间，比如：
  </p>
  
  <div class="informalexample">
   <div class="example-contents">
<div class="cdata"><pre>
(?i:saturday|sunday)
(?:(?i)saturday|sunday)
</pre></div>
   </div>

  </div>
  
  <p class="para">
  上面两种写法实际上是相同的模式。因为可选分支会从左到右尝试每个分支，
  并且选项没有在子模式结束前被重置，
  并且由于选项的设置会穿透对后面的其他分支产生影响，因此，
  上面的模式都会匹配 ”SUNDAY” 以及 ”Saturday”。
  </p>
  
  <p class="para">
  在 PHP 4.3.3 中，可以对子组使用 <em>(?P&lt;name&gt;pattern)</em> 的语法进行命名。
  这个子模式将会在匹配结果中同时以其名称和顺序(数字下标)出现， PHP
  5.2.2中又增加了两种味子组命名的语法：
  <em>(?&lt;name&gt;pattern)</em> 和 <em>(?’name’pattern)</em>。
  </p>

  <p class="para">
  有时需要多个匹配可以在一个正则表达式中选用子组。
  为了让多个子组可以共用一个后向引用数字的问题，
  <em>(?|</em> 语法允许复制数字。
  考虑下面的正则表达式匹配<em>Sunday</em>：
  </p>

  <div class="informalexample">
   <div class="example-contents">
<div class="cdata"><pre>(?:(Sat)ur|(Sun))day</pre></div>
   </div>

  </div>

  <p class="para">
  这里当后向引用 1 空时<em>Sun</em> 存储在后向引用 2 中.
  当后向引用 2 不存在的时候 <em>Sat</em> 存储在后向引用 1中。 使用
  <em>(?|</em>修改模式来修复这个问题：
  </p>

  <div class="informalexample">
   <div class="example-contents">
<div class="cdata"><pre>(?|(Sat)ur|(Sun))day</pre></div>
   </div>

  </div>

  <p class="para">
  使用这个模式，
  <em>Sun</em>和<em>Sat</em>都会被存储到后向引用1中。
  </p>
 </div><hr /><div class="manualnavbar" style="text-align: center;">
 <div class="prev" style="text-align: left; float: left;"><a href="regexp.reference.internal-options.html">内部选项设置</a></div>
 <div class="next" style="text-align: right; float: right;"><a href="regexp.reference.repetition.html">重复/量词</a></div>
 <div class="up"><a href="reference.pcre.pattern.syntax.html">PCRE 正则语法</a></div>
 <div class="home"><a href="index.html">PHP Manual</a></div>
</div></body></html>
